
require 'lfs'
require 'struct'

local path_base = getprojectbasepath()

if not path_base then
    return
end

local cab_id = 'CABINET'
local cab_header = "c" .. #cab_id .. "II"
local cab_size = struct.size(cab_header)

local run_path = exec.path:lower():gsub("guacpublish", "guacrun")

do
    if not lfs.attributes(path_base .. ".build.lua") then
        error("Build script not found (" .. path_base .. ".build.lua)",2)
    end
    local build_script = assert(loadfile(path_base .. ".build.lua"))
    
    local root = runbuildscript(build_script)
    
    local new_root
    
    local outfile = assert(io.open(path_base .. ".exe", 'wb'))
    do
        local infile = io.open(run_path, 'rb')
        do
            local buffer
            while true do
                buffer = infile:read(1024)
                if not buffer then  break;  end
                outfile:write(buffer)
            end
        end
        infile:close()
    
        local buf = {"local exec_path,file,folder = exec_path,file,folder; return ";
            write = function(self, ...)
                for i=1,select('#', ...) do  self[#self+1] = tostring(select(i, ...));  end
                return self
            end
        }
        
        local processdir
        processdir = function(d)
            buf:write('{')
            for k,v in pairs(d) do
                buf:write( ("[%q]="):format(k) )
                if type(v) == 'table' then
                    buf:write('folder')
                    processdir(v)
                else
                    buf:write('file{path=exec_path,offset=')
                    buf:write(outfile:seek())
                    
                    local ext = v:lower():match("([^%.]+)$")
                    
                    if (ext == 'lua') then
                    
                        local scriptbuf = {"local F = ...; return function(...) "}
                        
                    
                        local infile = assert(io.open(v, 'rb'))
                        do
                            local buffer
                            while true do
                                buffer = infile:read(1024)
                                if not buffer then  break;  end
                                scriptbuf[#scriptbuf+1] = buffer
                            end
                        end
                        infile:close()
                        
                        scriptbuf[#scriptbuf+1] = "\nend"
                        
                        local script = assert( loadstring(table.concat(scriptbuf), v) )
                        script = string.dump( script )
                        
                        buf:write(",compiled=true,length=")
                        buf:write(#script)
                        outfile:write(script)
                    
                    else
                        buf:write(',length=')
                        buf:write(lfs.attributes(v, 'size'))
                    
                        local infile = assert(io.open(v, 'rb'))
                        do
                            local buffer
                            while true do
                                buffer = infile:read(1024)
                                if not buffer then  break;  end
                                outfile:write(buffer)
                            end
                        end
                        infile:close()
                    end
                    
                    buf:write('}')
                end
                buf:write(';')
            end
            buf:write('}')
        end
        
        processdir(root)
        
        buf[#buf+1] = (", %q"):format(path_base:upper() .. ".RUN.LUA")
        
        local cab_chunk = string.dump( loadstring( table.concat(buf) ) )
        
        local cab_struct = struct.pack(cab_header, cab_id, outfile:seek(), #cab_chunk)
        
        outfile:write(cab_chunk)
        outfile:write(cab_struct)
    end
    outfile:close()
    
    showinfo("Publish successful!\n" .. path_base .. ".exe generated.")
    
    return
end

local cab_struct = struct.pack(cab_header,   cab_id, lfs.attributes(run_path,'size'), #cabinet_chunk)

local outpath = path_base .. ".exe"

local outfile = io.open(outpath, 'wb')
do
    local infile = io.open(run_path, 'rb')
    do
        local buffer
        while true do
            buffer = infile:read(1024)
            if not buffer then  break;  end
            outfile:write(buffer)
        end
    end
    infile:close()
end
outfile:close()

seticon(outpath, path_base .. '.ico')

outfile = io.open(outpath, 'rb')
do
	outfile:seek('end', 0)
	
    outfile:write(cabinet_chunk)
    
    outfile:write(cab_struct)
end
outfile:close()

showinfo("Publish successful!\n" .. path_base .. ".exe generated.")